var pm2        = require('pm2')
var os         = require('os');
var hostname   = os.hostname()
var nodemailer = require('nodemailer')
var markdown   = require('nodemailer-markdown').markdown
var config     = require('../config/config')._config
var _          = require('lodash.template')
var template   = require('fs').readFileSync(config.template)
var async      = require('async')
var util       = require('util')
var p          = require('path')
var ump        = require('../../src/utils/umpReport');

var queue           = []
var timeout         = null
var processerrorkey = 'wq.webmonitor.ptcxnode.marketmonitor.processerror';
var pm2bekilledkey  = 'wq.webmonitor.ptcxnode.marketmonitor.pm2bekilled';
var ip              = getIPAdress();
var gammaip         = config.gammaip;
var limit           = config.limit;

var bus = null;

var tableTpl = '<tr style="line-height: 25px;font-family:微软雅黑;"><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.name %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.NODE_ENV %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.pm_id %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= event %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.status %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.exec_mode %></td><td style="border:1px solid #ccc;font-family:微软雅黑;overflow: hidden;text-align: center;word-break:break-all;"><%= process.restart_time %></td></tr>';

function compile(template, data) {
    var s = _(template)
    return s(data)
}

function sendMail(opts) {
    console.log('sendMail begin')

    var transporter = nodemailer.createTransport(require('nodemailer-smtp-transport')(config.smtp))

    transporter.use('compile', markdown({useEmbeddedImages: true}))

    if (!opts.subject || !opts.text) {
        throw new ReferenceError("No text or subject")
    }

    var cansend = emailSendValid(config.emailetime, limit);
    cansend && (config.emailetime = cansend)

    if (ip == gammaip) {
        return;
    }
    if (!cansend) {
        return;
    }

    var opt = {
        from                : opts.from || config.mail.from,
        to                  : opts.to ? opts.to : config.mail.to,
        subject             : opts.subject,
        generateTextFromHTML: true,
        html                : formatHtml(opts),
        attachments         : opts.attachments || []
    }

    transporter.sendMail(opt, function (err, info) {
        if (err) {
            console.error(err)
        }

        transporter.close();
    })
}

function processQueue() {
    var l = queue.length

    if (l == 0) {
        return;
    }

    if (ip == gammaip) {
        return;
    }

    if (l === 1) {
        bussReport(processerrorkey);
        return sendMail(queue[0])
    }

    var text        = ''
    var attachments = []

    var subject = compile(config.subject, queue[0])

    for (var i in queue) {
        text += queue[i].text

        if (config.attach_logs) {

            for (var j in queue[i].attachments) {
                var has = false

                for (var a in attachments) {
                    if (attachments[a].path == queue[i].attachments[j].path) {
                        has = true
                        break;
                    }
                }

                if (has === false) {
                    attachments.push(queue[i].attachments[j])
                }
            }
        }

        bussReport(processerrorkey);
    }
    sendMail({
        subject    : subject,
        text       : text,
        attachments: attachments
    })

    queue.length = 0
}

function bussReport(key) {
    var umpclient = ump.bussReport.register(key);
    umpclient.addValueReport(1);
}

function formatHtml(opts) {
    var tpl = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><p><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255);">Hi,all</span><br style="white-space: normal; font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255);" /><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255);">&nbsp;</span><br style="white-space: normal; font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255);" /><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255);">&nbsp; &nbsp;<strong><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255); color: rgb(112, 48, 160);"> market</span></strong>进程出现异常/重启，ip：<strong><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; line-height: normal; background-color: rgb(255, 255, 255); color: rgb(112, 48, 160);">{hostname}</span></strong>请开发人员关注！</span><br style="white-space: normal;" /><br style="white-space: normal;" /><span style="color: rgb(112, 48, 160);"><strong><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; background-color: rgb(255, 255, 255);">说明</span></strong></span><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; background-color: rgb(255, 255, 255);">：异常日志打印在附件<strong><span style="color: rgb(112, 48, 160);">err.log</span></strong>中<br /></span></p><p><br /></p><table report_id="20718" class="mailJob" style="text-align:center;font-size:12px;border-collapse: collapse;width:98%;white-space: nowrap;;font-family:微软雅黑;"><thead><tr><th style="text-align: left;font-weight: bold;font-size: 16px;color: #1e558b; border:0px;border-bottom: 3px solid #387fb5;font-family:微软雅黑;" colspan="7">异常进程信息</th></tr><tr style="color: #666;font-weight: bold;line-height: 30px;font-size: 14px;font-family:微软雅黑;"><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">异常应用名</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">NODE_ENV</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">pm2进程号</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">异常事件</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">运行状态</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">运行模式</th><th rowspan="1" style="border:1px solid #ccc;text-align:center;font-family:微软雅黑;overflow:hidden;" colspan="1">重启次数</th></tr></thead><tbody>    {content}</tbody></table><p><br /></p><p><br /><span style="font-family: 微软雅黑, Tahoma; font-size: 14px; background-color: rgb(255, 255, 255);"><br /><br /><br /><br /><br /><br /><br /></span><br /></p><br /></body></html>';

    var html = tpl.replace("{hostname}", hostname)
        .replace("{content}", opts.text)

    return html;
}

function getIPAdress() {
    var interfaces = os.networkInterfaces();
    for (var devName in interfaces) {
        var iface = interfaces[devName];
        for (var i = 0; i < iface.length; i++) {
            var alias = iface[i];
            if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                return alias.address;
            }
        }
    }
}

function emailSendValid(emailtime, limit) {
    //获取当前时间
    var nowTime = +new Date().getTime();
    console.log(nowTime,emailtime,limit)
    if (nowTime - emailtime >= limit * 60 * 1000) {
        //距离上一次发送邮件超过了limit(直接返回true)
        emailtime = nowTime;
        return emailtime;
    }
    //代表距离上一次发送还没有limit
    return false;
};

exports.launchBus = function () {

    pm2.launchBus(function (err, bus) {

        if (err) {
            throw err
        }

        bus.on('process:event', function (e) {

            console.log('catch event', e.event);

            if (e.manually === true) {
                return;
            }

            if (~config.events.indexOf(e.event)) {

                e.date = new Date(e.at).toString()

                e = util._extend(e, {
                    hostname: hostname,
                    text    : compile(tableTpl, e),
                    subject : compile(config.subject, e)
                })

                if (config.attach_logs) {
                    e.attachments = [];
                    ['pm_err_log_path'].forEach(function (log) {
                        e.attachments.push({
                            filename: p.basename(e.process[log]),
                            path    : e.process[log]
                        })
                    })
                }

                queue.push(e)

                if (timeout) {
                    clearTimeout(timeout)
                }

                timeout = setTimeout(processQueue, config.polling)
            }
        })

        bus.on('pm2:kill', function () {
            bussReport(pm2bekilledkey);
            console.error('PM2 is beeing killed')
        })
    })
}